/*-------------------------------------------------------------------------
 *
 * IDENTIFICATION
 *	  fetchcatalogtable.c
 *
 *-------------------------------------------------------------------------
 */

#include "datadictionary.h"
#include "utils/syscache.h"
#include "access/genam.h"
#include "utils/snapmgr.h"
#include "access/htup_details.h"
#include "access/heapam.h"



static void add_tuple_to_cts(SingleCatalogCache *scc, HeapTuple tuple, int datasize);

bool
get_relation_oid_by_relname(char* relname, Oid* reloid, bool gettemptable)
{
	bool				result = false;
	Relation			pgclass = NULL;
#if (defined PG_VERSION_12)  || (defined PG_VERSION_13)
	SysScanDesc		scan = NULL;
#else
	HeapScanDesc		scan = NULL;
#endif
	HeapTuple			tuple = NULL;
	Form_pg_class 		classForm = NULL;
#if (defined PG_VERSION_12)  || (defined PG_VERSION_13)
	pgclass = table_open(RelationRelationId, AccessShareLock);
	scan = systable_beginscan(pgclass, 0, false,
							   SnapshotSelf, 0, NULL);
#else
	pgclass = heap_open(RelationRelationId, AccessShareLock);
	scan = heap_beginscan_catalog(pgclass, 0, NULL);
#endif

#if (defined PG_VERSION_12)  || (defined PG_VERSION_13)
	while ((tuple = systable_getnext(scan)) != NULL)
#else
	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
#endif
	{
		classForm = (Form_pg_class) GETSTRUCT(tuple);
		if(0 == strcmp(relname,classForm->relname.data))
		{
			if(gettemptable && RELPERSISTENCE_TEMP != classForm->relpersistence)
				continue;
			if(!gettemptable && PG_CATALOG_NAMESPACE != classForm->relnamespace)
				continue;
#if (defined PG_VERSION_12)  || (defined PG_VERSION_13)
			*reloid = classForm->oid;
#else
			*reloid = HeapTupleHeaderGetOid(tuple->t_data);
#endif
			result = true;
			break;
		}
	}
#if (defined PG_VERSION_12)  || (defined PG_VERSION_13)
	systable_endscan(scan);
	table_close(pgclass, AccessShareLock);
#else
	heap_endscan(scan);
	heap_close(pgclass, AccessShareLock);
#endif
	return result;
}

static void
add_tuple_to_cts(SingleCatalogCache *scc, HeapTuple tuple, int datasize)
{
	char	*data = NULL;
	
	data = GETSTRUCT(tuple) - sizeof(Oid);

	
	if(scc->totsize - scc->usesize < datasize)
		add_space_for_cts(scc, 0);
	
	memcpy(scc->cursor, data, datasize);
	scc->cth.elemnum++;
	scc->usesize += datasize;
	scc->cursor += datasize;
}

bool 
fetch_single_catalog(Oid reloid, int datasgsize, SingleCatalogCache *scc)
{
	bool				result = false;
	
	Relation			pgrel = NULL;
#if (defined PG_VERSION_12)  || (defined PG_VERSION_13)
	SysScanDesc			scan = NULL;
#else
	HeapScanDesc		scan = NULL;
#endif
	HeapTuple			tuple = NULL;

#if (defined PG_VERSION_12)  || (defined PG_VERSION_13)
	pgrel = table_open(reloid, AccessShareLock);
	if(!pgrel)
		ereport(ERROR,(errmsg("Open relation(oid:%d) failed",reloid)));
	scan = systable_beginscan(pgrel, 0, false,
							   SnapshotSelf, 0, NULL);

	while ((tuple = systable_getnext(scan)) != NULL)
	{
		add_tuple_to_cts(scc, tuple, datasgsize);
	}

	systable_endscan(scan);
	table_close(pgrel, AccessShareLock);
#else
	pgrel = heap_open(reloid, AccessShareLock);
	if(!pgrel)
		ereport(ERROR,(errmsg("Open relation(oid:%d) failed",reloid)));
	scan = heap_beginscan_catalog(pgrel, 0, NULL);

	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
	{
		add_tuple_to_cts(scc, tuple, datasgsize);
	}

	heap_endscan(scan);
	heap_close(pgrel, AccessShareLock);
#endif
	return result;
}

TupleDesc
makeOutputXlogDesc(void)
{
	TupleDesc tupdesc = NULL;
#if (defined PG_VERSION_12)  || (defined PG_VERSION_13)
	tupdesc = CreateTemplateTupleDesc(1);
#else
	tupdesc = CreateTemplateTupleDesc(1, false);
#endif
	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "path", TEXTOID, -1, 0);
	return tupdesc;
}